package com.example.demo.scheduledtask;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.example.demo.common.Constant;
import com.example.demo.config.ErpConfig;
import com.example.demo.mapper.PoMpsinfoMapper;
import com.example.demo.mapper.WmsPurchaseMapper;
import com.example.demo.mapper.WmsPurchaseNewMapper;
import com.example.demo.utils.SoapXmlUtil;
import com.example.demo.vo.PurchaseReceiptFormListReq2;
import com.example.demo.vo.PurchaseReceiptFormVo;
import com.example.demo.vo.SlStoreableVo;
import com.example.demo.vo.XmlResp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * @author : Zhang.yt
 * @date : 2024/7/29
 */
@Component
@Slf4j
@DS("wms")
public class PurchaseIn {
    @Resource
    private WmsPurchaseNewMapper wmsPurchaseNewMapper;

    @Autowired
    private SoapXmlUtil soapXmlUtil;

    @Resource
    private ErpConfig erpConfig;

    @Resource
    private WmsPurchaseMapper wmsPurchaseMapper;



    /**
     * 采购上架回写
     */
    @Scheduled(fixedDelay = 6 * 1000)//开启定时同步
//    @Async(value = "taskExecutor")
    public void purchaseIn() {
        //查询待回写的上架单
        PurchaseReceiptFormVo purchaseReceiptFormVo = wmsPurchaseNewMapper.getPurchaseIn();
        if (ObjectUtil.isEmpty(purchaseReceiptFormVo) || ObjectUtil.isEmpty(purchaseReceiptFormVo.getPmds055())) {
            log.info("未查询到采购上架回调数据，修改报错数据重新过账");
            wmsPurchaseMapper.purchaseInLose();
            return;
        }
        //来源单号
        String pmds055 = purchaseReceiptFormVo.getPmds055();
        try {
            //超过20秒未获取到锁就退出
//            if (!lock.tryLock(60, TimeUnit.SECONDS)) {
//                return;
//            }
            //查询要回写的细表
            List<PurchaseReceiptFormListReq2> purchaseReceiptFormListReq2s = wmsPurchaseNewMapper.getgetPurchaseInListNew(purchaseReceiptFormVo.getPmds055());
            if (CollUtil.isEmpty(purchaseReceiptFormListReq2s)) {
                wmsPurchaseNewMapper.updatePurchaseInOpflg(purchaseReceiptFormVo.getPmds055(), 2, "明细列表为空请确认！");
                return;
            }
            List<String> mcodeList = purchaseReceiptFormListReq2s.stream().map(PurchaseReceiptFormListReq2::getPmdt006).distinct().collect(Collectors.toList());
            //查询送货单关联收货单可入库数据
            List<SlStoreableVo> slStoreableVoList = wmsPurchaseNewMapper.getSlStoreableVoList(purchaseReceiptFormVo.getSourceid(), mcodeList);
            if (CollUtil.isEmpty(slStoreableVoList)) {
                wmsPurchaseNewMapper.updatePurchaseInOpflg(purchaseReceiptFormVo.getPmds055(), 2, "查询到的erp可入库数量为空，请确认！");
                return;
            } else {
                //料号可入库数量是否足够
                for (PurchaseReceiptFormListReq2 purchaseReceiptFormListReq2 : purchaseReceiptFormListReq2s) {
                    //入库上架数量
                    BigDecimal pmdt020 = purchaseReceiptFormListReq2.getPmdt020();
                    BigDecimal reduce = slStoreableVoList.stream().filter(item -> purchaseReceiptFormListReq2.getPmdt006().equals(item.getPmdt006())
                            && purchaseReceiptFormListReq2.getPmdt018().equals(item.getPmdt018())).map(SlStoreableVo::getQty).reduce(BigDecimal.ZERO, BigDecimal::add);
                    if (pmdt020.compareTo(reduce) > 0) {
                        wmsPurchaseNewMapper.updatePurchaseInOpflg(purchaseReceiptFormVo.getPmds055(), 2, "料号:" + purchaseReceiptFormListReq2.getPmdt006() + "批次:" + purchaseReceiptFormListReq2.getPmdt018() + "查询到的erp可入库数量为空，请确认！");
                        return;
                    }
                }
            }
            purchaseReceiptFormVo.setActionType(Constant.ActionType_I);
            purchaseReceiptFormVo.setPmdssite(Constant.PMDSSITE_AMA);
            List<PurchaseReceiptFormListReq2> sendReqList = new ArrayList<>();

            Map<String, List<SlStoreableVo>> collect = slStoreableVoList.stream().collect(Collectors.groupingBy(SlStoreableVo::getPmdsdocno));
            if (collect.keySet().size() > 1) {
                //多个收货单收货情况
                for (PurchaseReceiptFormListReq2 purchaseReceiptFormListReq2 : purchaseReceiptFormListReq2s) {
                    //回写数量
                    BigDecimal pmdt020 = purchaseReceiptFormListReq2.getPmdt020();
                    for (Map.Entry<String, List<SlStoreableVo>> listEntry : collect.entrySet()) {
                        computeItem(listEntry.getValue(), pmdt020, sendReqList, purchaseReceiptFormListReq2);
                        //上架数量为0时跳出循环
                        if (pmdt020.compareTo(BigDecimal.ZERO) <= 0) {
                            break;
                        }
                    }
                }
            } else {
                //单个收货单直接计算项次
                String pmdsdocno = slStoreableVoList.get(0).getPmdsdocno();
                purchaseReceiptFormVo.setPmds006(pmdsdocno);
                for (PurchaseReceiptFormListReq2 purchaseReceiptFormListReq2 : purchaseReceiptFormListReq2s) {
                    //回写数量
                    BigDecimal pmdt020 = purchaseReceiptFormListReq2.getPmdt020();
                    computeItem(slStoreableVoList, pmdt020, sendReqList, purchaseReceiptFormListReq2);
                }
            }
            //
            if (CollUtil.isEmpty(sendReqList)) {
                wmsPurchaseNewMapper.updatePurchaseInOpflg(purchaseReceiptFormVo.getPmds055(), 2, "数据分发项次失败，请联系开发人员处理");
                return;
            }
            //如果有多个收货单的情况则需要分开回写
            Map<String, List<PurchaseReceiptFormListReq2>> listMap = sendReqList.stream().collect(Collectors.groupingBy(PurchaseReceiptFormListReq2::getPmds006));
            if (listMap.keySet().size() > 1) {
                ArrayList<String> pmdsdocnoList = new ArrayList<>();
                for (Map.Entry<String, List<PurchaseReceiptFormListReq2>> listEntry : listMap.entrySet()) {
                    purchaseReceiptFormVo.setPmds055(pmds055 + "-" + System.currentTimeMillis());
                    if (ObjectUtil.isEmpty(purchaseReceiptFormVo.getPmds011())) {
                        purchaseReceiptFormVo.setPmds011(collect.get(listEntry.getKey()).get(0).getPmds011());
                        purchaseReceiptFormVo.setPmdsdocno(purchaseReceiptFormVo.getPmds011() == 1 ? Constant.PMDSDOCNO_3501 : Constant.PMDSDOCNO_3510);
                    }
                    purchaseReceiptFormVo.setPmds006(listEntry.getKey());
                    //获取回写json
                    String resMessage = soapXmlUtil.getSoapXml("PurchaseIn", "pmds_t", "pmdt_t", purchaseReceiptFormVo, listEntry.getValue());
                    log.info("采购入库回写:{}", resMessage);
                    wmsPurchaseNewMapper.updatePurchaseInOpflg(pmds055, 3, "erp待返回");
                    //发送soap消息，并解析结果
                    String result;
                    try {
                        result = soapXmlUtil.sendSoapMessageNew(resMessage, erpConfig.getUrl());
                    } catch (Exception e) {
                        result = soapXmlUtil.sendSoapMessageNew(resMessage, erpConfig.URL2);
                    }
                    //调用等待
                    if (listEntry.getValue().size() >= 50) {
                        Thread.sleep(60 * 1000);
                    } else if (listEntry.getValue().size() >= 30) {
                        Thread.sleep(30 * 1000);
                    } else if (listEntry.getValue().size() >= 10) {
                        Thread.sleep(5 * 1000);
                    }
                    log.info("soap接口采购入库回调->{}", result);
                    XmlResp xmlResp = soapXmlUtil.analysisXml(result);
                    if (xmlResp.getCode().equals("0")) {
                        pmdsdocnoList.add(xmlResp.getData().get("pmdsdocno"));
                        //更新wms已回填数量
                        for (PurchaseReceiptFormListReq2 listReq2 : listEntry.getValue()) {
                            if (ObjectUtil.isNotEmpty(listReq2.getPmdt017())) {
                                listReq2.setPmdt016(listReq2.getPmdt016() + "#" + listReq2.getPmdt017());
                            }
                            wmsPurchaseNewMapper.updatePurchaseInreturnQty(listReq2, pmds055);
                        }
                        //更新erp收货单已入库数量
                        wmsPurchaseNewMapper.updatePurchaseReceiptDetails(purchaseReceiptFormVo.getPmds006());
                    } else {
                        //更新相应主表状态为回填失败
                        wmsPurchaseNewMapper.updatePurchaseInOpflg(pmds055, 2, xmlResp.getMessage());
                        return;
                    }
                }
                String join = StringUtils.join(pmdsdocnoList, ",");
                //更新相应主表状态为回填成功
                wmsPurchaseNewMapper.updatePurchaseInOpflg(pmds055, 1, join);
                //更新wsm及仓库上上架入库数量
                wmsPurchaseNewMapper.wmsSrmUpStockqty(purchaseReceiptFormVo.getPmds055());
            } else {
                if (ObjectUtil.isEmpty(purchaseReceiptFormVo.getPmds011())) {
                    purchaseReceiptFormVo.setPmds011(slStoreableVoList.get(0).getPmds011());
                    purchaseReceiptFormVo.setPmdsdocno(purchaseReceiptFormVo.getPmds011() == 1 ? Constant.PMDSDOCNO_3501 : Constant.PMDSDOCNO_3510);
                }
                purchaseReceiptFormVo.setPmds006(sendReqList.get(0).getPmds006());
                purchaseReceiptFormVo.setPmds055(purchaseReceiptFormVo.getPmds055() + '-' + System.currentTimeMillis());
                //获取回写json
                String resMessage = soapXmlUtil.getSoapXml("PurchaseIn", "pmds_t", "pmdt_t", purchaseReceiptFormVo, sendReqList);
                log.info("采购入库回写:{}", resMessage);
                wmsPurchaseNewMapper.updatePurchaseInOpflg(pmds055, 3, "erp待返回");
                //发送soap消息，并解析结果
                String result;
                try {
                    result = soapXmlUtil.sendSoapMessageNew(resMessage, erpConfig.getUrl());
                } catch (Exception e) {
//                    log.info("采购入库回写调用erp接口异常，尝试调用url2");
                    result = soapXmlUtil.sendSoapMessageNew(resMessage, erpConfig.URL2);
                }
                //调用等待
//                if (sendReqList.size() >= 50) {
//                    Thread.sleep(100 * 1000);
//                } else if (sendReqList.size() >= 30) {
//                    Thread.sleep(60 * 1000);
//                } else if (sendReqList.size() >= 10) {
//                    Thread.sleep(30 * 1000);
//                } else if (sendReqList.size() >= 5) {
//                    Thread.sleep(10 * 1000);
//                }
                log.info("soap接口采购入库回调->{}", result);
                XmlResp xmlResp = soapXmlUtil.analysisXml(result);
                if (xmlResp.getCode().equals("0")) {
                    //更新相应主表状态为回填成功
                    wmsPurchaseNewMapper.updatePurchaseInOpflg(pmds055, 1, xmlResp.getData().get("pmdsdocno"));
                    //更新wms已回填数量
                    for (PurchaseReceiptFormListReq2 listReq2 : sendReqList) {
                        if (ObjectUtil.isNotEmpty(listReq2.getPmdt017())) {
                            listReq2.setPmdt016(listReq2.getPmdt016() + "#" + listReq2.getPmdt017());
                        }
                        wmsPurchaseNewMapper.updatePurchaseInreturnQty(listReq2, pmds055);
                    }
                    //更新erp收货单已入库数量
                    wmsPurchaseNewMapper.updatePurchaseReceiptDetails(purchaseReceiptFormVo.getPmds006());
                    //更新wsm及仓库上上架入库数量
                    wmsPurchaseNewMapper.wmsSrmUpStockqty(pmds055);
                } else {
                    //更新相应主表状态为回填失败
                    wmsPurchaseNewMapper.updatePurchaseInOpflg(pmds055, 2, xmlResp.getMessage());
                }
            }

        } catch (Exception e) {
            wmsPurchaseNewMapper.updatePurchaseInOpflg(pmds055, 2, "非常见的数据处理问题，请联系开发人员处理");

            e.printStackTrace();
        }
//        finally {
//            log.error("finally释放锁{}", this.getClass().getName());
//            if (ObjectUtil.isNotEmpty(lock) && lock.isHeldByCurrentThread()) {
//                lock.unlock();
//            }
//        }

    }

    private void computeItem(List<SlStoreableVo> slStoreableVoList, BigDecimal pmdt020, List<PurchaseReceiptFormListReq2> sendReqList, PurchaseReceiptFormListReq2 purchaseReceiptFormListReq2) {
        List<SlStoreableVo> slStoreableVos = slStoreableVoList.stream().filter(item -> purchaseReceiptFormListReq2.getPmdt006().equals(item.getPmdt006())
                && purchaseReceiptFormListReq2.getPmdt018().equals(item.getPmdt018())).collect(Collectors.toList());
        //有多个项次数据时需要分发项次及数量
        for (SlStoreableVo slStoreableVo : slStoreableVos) {
            PurchaseReceiptFormListReq2 copyProperties = BeanUtil.copyProperties(purchaseReceiptFormListReq2, PurchaseReceiptFormListReq2.class);
            copyProperties.setPmdt028(slStoreableVo.getPmdtseq());
            copyProperties.setPmds006(slStoreableVo.getPmdsdocno());
            if (pmdt020.compareTo(slStoreableVo.getQty()) > 0) {
                copyProperties.setPmdt020(slStoreableVo.getQty());
                pmdt020 = pmdt020.subtract(slStoreableVo.getQty());
            } else {
                copyProperties.setPmdt020(pmdt020);
                pmdt020 = BigDecimal.ZERO;
            }
            sendReqList.add(copyProperties);
            if (pmdt020.compareTo(BigDecimal.ZERO) <= 0) {
                break;
            }
        }
    }
}
